/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.opmviewer.graphviz;

import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.HashMap;
import java.util.Map;
import org.apache.batik.parser.AWTPathProducer;
import org.apache.batik.parser.AWTPolylineProducer;
import org.apache.batik.parser.PathParser;
import org.apache.batik.parser.PointsParser;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import prefuse.render.ShapeRenderer;

/**
 *
 * @author grzegorz
 */
public class SVGGraphHandler extends DefaultHandler {

    private Map<String, EdgeShape> edgeShapes;
    private Map<Integer, Rectangle2D> nodeRects;
    private String id = "";
    private boolean inside_node = false;
    private boolean inside_edge = false;
    private boolean inside_title = false;
    private boolean skipped = false;
    private EdgeShape currShape = null;
    private ShapeRenderer sr = null;

    public SVGGraphHandler() {
        edgeShapes = new HashMap<String, EdgeShape>();
        nodeRects = new HashMap<Integer, Rectangle2D>();
        sr = new ShapeRenderer();
    }

    @Override
    public void startElement(String namespaceURI, String localName,
            String qName, Attributes atts) throws SAXException {
        System.err.println(qName);
        if (qName.equals("g") && !skipped) {
            skipped = true;
        } else if (qName.equals("g") && atts.getValue("id").startsWith("node")) {
            inside_node = true;
        } else if (qName.equals("g") && atts.getValue("id").startsWith("edge")) {
            inside_edge = true;
        } else if (!(inside_edge || inside_node)) {
            //do nothing
        } else if (qName.equals("title")) {
            inside_title = true;
            id = "";
        } else if (qName.equals("polygon") && inside_node) {
            String ptstring = atts.getValue("points");
            String[] ptstrs = new String[5];
            ptstrs = ptstring.split(" ");
            Point2D[] points  = new Point2D[4];
            for(int i = 0; i < 4; ++i){
                String[] coords = new String[2];
                coords = ptstrs[i].split(",");
                points[i] = new Point2D.Double(Double.parseDouble(coords[0]),
                       Double.parseDouble(coords[1]));
            }

            double x = points[1].getX();
            double y = points[1].getY();
            double w = points[3].getX() - x;
            double h = points[3].getY() - y;
            nodeRects.put(Integer.parseInt(id),
                    new Rectangle2D.Double(x, y, w, h));

        } else if (qName.equals("path")) {
            currShape = new EdgeShape();
            String path = atts.getValue("d");
            AWTPathProducer awtpath = new AWTPathProducer();
            PathParser ppar = new PathParser();
            ppar.setPathHandler(awtpath);
            ppar.parse(path);
            (currShape = new EdgeShape()).line = awtpath.getShape();
        } else if (qName.equals("polygon") && inside_edge) {
            String polygon = atts.getValue("points");
            AWTPolylineProducer awtpoly = new AWTPolylineProducer();
            PointsParser ptpar = new PointsParser();
            ptpar.setPointsHandler(awtpoly);
            ptpar.parse(polygon);
            currShape.arrow = awtpoly.getShape();
            edgeShapes.put(id, currShape);
        }
    }

    @Override
    public void characters(char ch[], int start, int length) {
        if ((inside_node || inside_edge) && inside_title) {
            id += new String(ch, start, length);
        }
    }

    @Override
    public void endElement(String namespaceURI, String localName, String qName)
            throws SAXException {
        if (qName.equals("g")) {
            inside_node = false;
            inside_edge = false;
        } else if (qName.equals("title")) {
            inside_title = false;
        }
    }

    /**
     * @return map from string representation of edge to the edge's shape
     */
    public Map<String, EdgeShape> getEdgeShapes() {
        return edgeShapes;
    }

    /**
     * @return map from node ID to its bounding rectangle
     */
    public Map<Integer, Rectangle2D> getNodeRects() {
        return nodeRects;
    }
}
